#pragma once

#include <memory>
#include "Containers/ThreadSafePtr.h"   
#include "Task.h"
#include "Future.h"
#include "Async.h"

class WHENGINE_API CPackagedTaskBase
{
public:    
    virtual TThreadSafeSharedPtr<CTaskBase> GetLowLevel() const =0;
    virtual bool IsFinished() const  =0;
    virtual bool IsFailed() const =0;
    //is Start()  invoked
    virtual bool IsStarted() const =0;
    virtual void Start() =0;

};

template<typename ReultType>
class CPackagedTask : public CPackagedTaskBase
{
public:    
    CPackagedTask()
    {
    }

    void Initialize(ISchedule* InSchedule
        ,const typename CTask<ReultType>::FunctionType & InFun)
    {
        Task= WH::MakeThreadSafeSharedPtr<CTask<ReultType>>(InSchedule,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    void Initialize(ISchedule* InSchedule
        ,typename CTask<ReultType>::FunctionType && InFun)
    {
        Task= WH::MakeThreadSafeSharedPtr<CTask<ReultType>>(InSchedule,std::move(InFun));
    }

    //raw pointer version
    void Initialize(ISchedule* InSchedule
        , typename CTask<ReultType>::RawFunctionType InFun )
    {
        Task= WH::MakeThreadSafeSharedPtr<CTask<ReultType>>(InSchedule,InFun);
    }

    CPackagedTask(ISchedule* InSchedule
        ,const typename CTask<ReultType>::FunctionType & InFun)
    {
        Initialize(InSchedule,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    CPackagedTask(ISchedule* InSchedule
        ,typename CTask<ReultType>::FunctionType && InFun)
    {
        Initialize(InSchedule,std::move(InFun));
    }

    //raw pointer version
    CPackagedTask(ISchedule* InSchedule
        ,typename CTask<ReultType>::RawFunctionType InFun )
    {
        Initialize(InSchedule,InFun);
    }

    ~CPackagedTask()
    {
    }

    const TThreadSafeSharedPtr<CTask<ReultType>>& Unpack() const
    {
        return Task;
    }

    TThreadSafeSharedPtr<CTaskBase> GetLowLevel() const override
    {
        return WH::StaticCastThreadSafeSharedPtr<CTaskBase>(Task);
    }

    bool IsFinished() const override
    {
        return Task->IsFinished();
    }

    bool IsFailed() const override
    {
        return Task->IsFailed();
    }

    CFuture<ReultType> GetFuture()
    {
        return CFuture<ReultType>(Task);
    }

    ReultType& GetResult()
    {
        assert(Task->IsFinished());
        return Task->GetResult();
    }

    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> Then(
        ISchedule* InSchedule
        ,const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        auto PackagedNextTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->NextTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedNextTask->Task);
        return PackagedNextTask;
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> Then(
        ISchedule* InSchedule
        ,typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        auto PackagedNextTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,std::move(InFun));

        this->Task->NextTask = WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedNextTask->Task);
        return PackagedNextTask;
    }

    //raw pointer version
    template<typename NewFunctionReturnType, typename RawFunctionType=NewFunctionReturnType(*)(bool& /*out succeed*/ )>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> Then(
        ISchedule* InSchedule ,
        RawFunctionType InFun)
        //typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        auto PackagedNextTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->NextTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedNextTask->Task);
        return PackagedNextTask;
    }   

    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> Then(
        std::shared_ptr<CPackagedTask<NewFunctionReturnType>> InThenTask)
    {
        this->Task->NextTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(InThenTask->Task);
        return InThenTask;
    }

    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenIfFailed(
        ISchedule* InSchedule
        ,const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        auto PackagedFailedTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedFailedTask->Task);
        return PackagedFailedTask;
    }    

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenIfFailed(
        ISchedule* InSchedule
        ,typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        auto PackagedFailedTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,std::move(InFun));

        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedFailedTask->Task);
        return PackagedFailedTask;
    }

    //raw pointer version
    template<typename NewFunctionReturnType,typename RawFunctionType=NewFunctionReturnType(*)(bool& /*out succeed*/ )>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenIfFailed(
        ISchedule* InSchedule
        ,RawFunctionType InFun)
    {
        auto PackagedFailedTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedFailedTask->Task);
        return PackagedFailedTask;
    }
    
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenIfFailed(
        std::shared_ptr<CPackagedTask<NewFunctionReturnType>> InThenTask)
    {
        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(InThenTask->Task);
        return InThenTask;
    }

    //then in main thread
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInMainThread(
        const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInMainThread(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInMainThread(
        typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    //then in main thread if failed
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInMainThreadIfFailed(
        const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInMainThreadIfFailed(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInMainThreadIfFailed(
        typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    //then in  thread pool
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInThreadPool(
        const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInThreadPool(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType,typename RawFunctionType=NewFunctionReturnType(*)(bool& /*out succeed*/ )>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInThreadPool(
         RawFunctionType InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

    //then in  thread pool if failed
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInThreadPoolIfFailed(
        const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInThreadPoolIfFailed(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType,typename RawFunctionType=NewFunctionReturnType(*)(bool& /*out succeed*/ )>
    std::shared_ptr<CPackagedTask<NewFunctionReturnType>> ThenInThreadPoolIfFailed(
        RawFunctionType InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

    bool IsStarted() const override
    {
        return !Task->IsJustCreated();
    }

    void Start() override
    {
        Task->AddToSchedule();
    }

    //immediately run in current thread
    //return is finished,might return false when condition is not satisfied
    bool RunInThisThread()
    {
        return Task->Do();
    }

//protected:
    TThreadSafeSharedPtr<CTask<ReultType>> Task;

};


template<>
class CPackagedTask<void> : public CPackagedTaskBase
{
public:    
    using ReultType=void;

    CPackagedTask()
    {
    }

    void Initialize(ISchedule* InSchedule
        ,const typename CTask<ReultType>::FunctionType & InFun)
    {
        Task= WH::MakeThreadSafeSharedPtr<CTask<ReultType>>(InSchedule,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    void Initialize(ISchedule* InSchedule
        ,typename CTask<ReultType>::FunctionType && InFun)
    {
        Task= WH::MakeThreadSafeSharedPtr<CTask<ReultType>>(InSchedule,std::move(InFun));
    }

    //raw pointer version
    void Initialize(ISchedule* InSchedule
        , CTask<ReultType>::RawFunctionType InFun )
    {
        Task= WH::MakeThreadSafeSharedPtr<CTask<ReultType>>(InSchedule,InFun);
    }

    CPackagedTask(ISchedule* InSchedule
        ,const typename CTask<ReultType>::FunctionType & InFun)
    {
        Initialize(InSchedule,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    CPackagedTask(ISchedule* InSchedule
        ,typename CTask<ReultType>::FunctionType && InFun)
    {
        Initialize(InSchedule,std::move(InFun));
    }

    //raw pointer version
    CPackagedTask(ISchedule* InSchedule
        , CTask<ReultType>::RawFunctionType InFun )
    {
        Initialize(InSchedule,InFun);
    }

    ~CPackagedTask()
    {
    }


    const TThreadSafeSharedPtr<CTask<ReultType>>& Unpack() const
    {
        return Task;
    }

    TThreadSafeSharedPtr<CTaskBase> GetLowLevel() const override
    {
        return WH::StaticCastThreadSafeSharedPtr<CTaskBase>(this->Task);
    }

    bool IsFinished() const override
    {
        return Task->IsFinished();
    }

    bool IsFailed() const override
    {
        return Task->IsFailed();
    }

    CFuture<ReultType> GetFuture()
    {
        return CFuture<ReultType>(Task);
    }


    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> Then(
        ISchedule* InSchedule
        ,const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        auto PackagedNextTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->NextTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedNextTask->Task);
        return PackagedNextTask;
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> Then(
        ISchedule* InSchedule
        ,typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        auto PackagedNextTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,std::move(InFun));

        this->Task->NextTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedNextTask->Task);
        return PackagedNextTask;
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> Then(
        ISchedule* InSchedule 
        ,typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        auto PackagedNextTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->NextTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedNextTask->Task);
        return PackagedNextTask;
    }

    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> Then(
        std::shared_ptr<CPackagedTask<NewFunctionReturnType>> InThenTask)
    {
        this->Task->NextTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(InThenTask->Task);
        return InThenTask;
    }

    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenIfFailed(
        ISchedule* InSchedule
        ,const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        auto PackagedFailedTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedFailedTask->Task);
        return PackagedFailedTask;
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenIfFailed(
        ISchedule* InSchedule
        ,typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        auto PackagedFailedTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,std::move(InFun));

        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedFailedTask->Task);
        return PackagedFailedTask;
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenIfFailed(
        ISchedule* InSchedule
        ,typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        auto PackagedFailedTask= std::make_shared<CPackagedTask<NewFunctionReturnType>>(
            InSchedule
            ,InFun);

        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(PackagedFailedTask->Task);
        return PackagedFailedTask;
    }

    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenIfFailed(
        std::shared_ptr<CPackagedTask<NewFunctionReturnType>> InThenTask)
    {
        this->Task->FailedTask=WH::StaticCastThreadSafeSharedPtr<CTaskBase>(InThenTask->Task);
        return InThenTask;
    }

    //then in main thread
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInMainThread(
        const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInMainThread(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInMainThread(
        typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInMainThreadIfFailed(
       const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInMainThreadIfFailed(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInMainThreadIfFailed(
        typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->MainThread,InFun);
    }

    //then in  thread pool
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInThreadPool(
        const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInThreadPool(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInThreadPool(
        typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        return Then<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

    //then in  thread pool if failed
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInThreadPoolIfFailed(
       const typename CTask<NewFunctionReturnType>::FunctionType & InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInThreadPoolIfFailed(
        typename CTask<NewFunctionReturnType>::FunctionType && InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,std::move(InFun));
    }

    //raw pointer version
    template<typename NewFunctionReturnType>
    std::shared_ptr<CPackagedTaskBase> ThenInThreadPoolIfFailed(
        typename CTask<NewFunctionReturnType>::RawFunctionType InFun)
    {
        return ThenIfFailed<NewFunctionReturnType>(CAsyncSystem::Get()->ThreadPool,InFun);
    }

//protected:
    bool IsStarted() const override
    {
        return !Task->IsJustCreated();
    }

    void Start() override
    {
        Task->AddToSchedule();
    }


    //immediately run in current thread
    //return is finished,might return false when condition is not satisfied
    bool RunInThisThread()
    {
        return Task->Do();
    }

    TThreadSafeSharedPtr<CTask<ReultType>> Task;
};

namespace WH
{
    template<typename ReturnType>
    static std::shared_ptr<CPackagedTask<ReturnType>>  CreateAsyncTask(
        const typename CTask<ReturnType>::FunctionType & Function)
    {
        auto Task = std::make_shared<CPackagedTask<ReturnType>>(
            CAsyncSystem::Get()->ThreadPool
            , Function);
        return Task;
    }

    //使用右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename ReturnType>
    static std::shared_ptr<CPackagedTask<ReturnType>>  CreateAsyncTask(
         typename CTask<ReturnType>::FunctionType && Function)
    {
        auto Task = std::make_shared<CPackagedTask<ReturnType>>(
            CAsyncSystem::Get()->ThreadPool
            , std::move(Function));
        return Task;
    }


    //raw pointer version
    template<typename ReturnType>
    static std::shared_ptr<CPackagedTask<ReturnType>>  CreateAsyncTask(
        typename CTask<ReturnType>::RawFunctionType Function)
    {
        auto Task = std::make_shared<CPackagedTask<ReturnType>>(
            CAsyncSystem::Get()->ThreadPool
            , Function);
        return Task;
    }

    template<typename ReturnType>
    static std::shared_ptr<CPackagedTask<ReturnType>> CreateMainThreadTask(
        const typename CTask<ReturnType>::FunctionType & Function)
    {
        auto Task = std::make_shared<CPackagedTask<ReturnType>>(
            CAsyncSystem::Get()->MainThread
            , Function);
        return Task;
    }

    //右值引用版本
    //当函数是lambda时，其捕获的变量会被拷贝到lambda内部，如果变量是大对象，会有性能问题
    //使用右值引用可以避免这个问题
    template<typename ReturnType>
    static std::shared_ptr<CPackagedTask<ReturnType>> CreateMainThreadTask(
        typename CTask<ReturnType>::FunctionType && Function)
    {
        auto Task = std::make_shared<CPackagedTask<ReturnType>>(
            CAsyncSystem::Get()->MainThread
            , std::move(Function));
        return Task;
    }

    //raw pointer version
    template<typename ReturnType>
    static std::shared_ptr<CPackagedTask<ReturnType>> CreateMainThreadTask(
        typename CTask<ReturnType>::RawFunctionType Function)
    {
        auto Task = std::make_shared<CPackagedTask<ReturnType>>(
            CAsyncSystem::Get()->MainThread
            , Function);
        return Task;
    }

    //run task and next task and next next ..
    //will block main thread until all task finished
    //if task is not started, will auto start 
    //Only allow invoke in main thread
    WHENGINE_API void BlockUntilFinished(std::shared_ptr<CPackagedTaskBase> InPackagedTask);


}